package tt.dz.egobus.servicemanager.bean;

import java.util.Map;
import java.util.ServiceLoader;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @author Anson
 * @date 17-3-29
 * @name sfi的逻辑算法工厂
 * @since 1.0.3
 */
public abstract class SPIAbstractIdAlgorithmFactory<T extends IdAlgorithm> {

    protected final Map<String, T> ALGORITHM_MAP = new ConcurrentHashMap<String, T>();

    /**
     * @author Anson
     * @date 17-3-29
     * @name 获取当前serviceloader
     * @since 1.0.3
     */
    protected abstract SPIServiceLoader getSFIServiceLoader();

    /**
     * @author Anson
     * @date 17-3-29
     * @name 获取当前算法的接口class
     * @since 1.0.3
     */
    protected abstract Class<T> getCurInterfaceClass();

    private volatile boolean isServiceLoaded = false;

    private ServiceLoader<T> serviceLoader;

    /**
     * @author Anson
     * @date 17-3-29
     * @name 根据算法初始化
     * @since 1.0.3
     */
    protected void init() {
        if (isServiceLoaded) {
            return;
        }
        this.serviceLoader = getServiceLoader();
        if (serviceLoader != null) {
            for (T t : serviceLoader) {
                ALGORITHM_MAP.putIfAbsent(t.id(), t);
            }
        }
        isServiceLoaded = true;
    }


    /**
     * @param id 当前算法的id
     * @author Anson
     * @date 17-3-29
     * @name 根据算法id获取算法实例
     * @since 1.0.3
     */
    protected T get(String id) {
        if (!this.isServiceLoaded) {
            this.init();
        }
        return this.ALGORITHM_MAP.get(id);
    }

    /**
     * @param id            当前算法的id
     * @author Anson
     * @date 17-3-29
     * @name 根据算法id获取算法重新创建实例
     * @since 1.0.3
     */
    protected T getNew(String id) {
        T object = null;
        if (this.serviceLoader == null) {
            this.serviceLoader = this.getServiceLoader();
        }
        for (T t : serviceLoader) {
            if (t.id().equals(id)) {
                object = t;
                break;
            }
        }

        return object;
    }

    /**
     * @author Anson
     * @date 17-3-29
     * @name 获取当前ServiceLoader
     * @since 1.0.3
     */
    protected ServiceLoader<T> getServiceLoader() {
        SPIServiceLoader sfiServiceLoader = this.getSFIServiceLoader();
        return sfiServiceLoader.serviceLoader(getCurInterfaceClass());
    }
}
